package com.zhou.framework.redis.util;

import com.zhou.framework.redis.script.MaxCountQueryScript;
import com.zhou.framework.redis.script.MaxCountScript;
import com.zhou.util.ObjectUtil;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * @author lang.zhou
 * @date 2022/4/7 11:42
 */
@Component
@SuppressWarnings("all")
public class RedisUtil {
    public RedisTemplate redisTemplate;

    private MaxCountScript maxCountScript;
    private MaxCountQueryScript maxCountQueryScript;

    public RedisUtil(RedisTemplate redisTemplate,MaxCountScript maxCountScript, MaxCountQueryScript maxCountQueryScript) {
        this.redisTemplate = redisTemplate;
        this.maxCountScript = maxCountScript;
        this.maxCountQueryScript = maxCountQueryScript;
    }

    public <T> T get(String dataKey){
        ValueOperations ops = redisTemplate.opsForValue();
        return (T) ops.get(dataKey);
    }
    public void set(String key,Object value,long second){
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set(key,value,second, TimeUnit.SECONDS);
    }
    public void set(String key,Object value){
        ValueOperations ops = redisTemplate.opsForValue();
        ops.set(key,value);
    }
    public void setHash(String type,Object key,Object value){
        HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
        ops.put(type,String.valueOf(key),value);
    }
    public void setHash(String type, Map<?,?> map){
        HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
        ops.putAll(type,map);
    }
    public <T> T getHash(String type,Object key){
        HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
        return (T) ops.get(type, key);
    }
    public <T> T getHashMap(String type){
        HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
        return (T) ops.entries(type);
    }
    public boolean del(String key){
        Boolean b = redisTemplate.delete(key);
        return ObjectUtil.saveToBoolean(b,false);
    }
    public boolean delHash(String type ,String key){
        Long n = redisTemplate.opsForHash().delete(type, key);
        return n > 0;
    }
    public Long incr(String key, Integer n){
        //return redisTemplate.opsForValue().increment(key, n.longValue());
        return redisTemplate.opsForValue().increment(key, n.longValue());
    }
    public boolean hasKey(String key){
        return redisTemplate.hasKey(key);
    }

    public int luaSet(Object key, Object value, Long seconds){

        DefaultRedisScript<Integer> redisScript = new DefaultRedisScript<>();
        //设置返回值类型
        redisScript.setResultType(Integer.class);
        String script = "if redis.call('SET',KEYS[1],ARGV[1]) then \n" +
                "   redis.call('EXPIRE',KEYS[1],ARGV[2]) return 1\n" +
                "else return 0 end";
        redisScript.setScriptText(script);

        return (int) redisTemplate.execute(redisScript, Collections.singletonList(key),value,seconds);
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(final String pattern) {
        return redisTemplate.keys(pattern);
    }

    public Long incr(String key,int maxCount, int time){
        List<String> keys = Collections.singletonList(key);
        return  (Long) redisTemplate.execute(maxCountScript, keys, maxCount, time);
    }
    public Long incrNow(String key){
        List<String> keys = Collections.singletonList(key);
        return  (Long) redisTemplate.execute(maxCountQueryScript, keys);
    }
}
